using System;
using System.Data;
using System.Collections.Generic;

namespace SharpObjects.Data
{
	/// <summary>
	/// IDb allows an application to work with a database without knowing the implementation details.
	/// This inteface must be implemented by a Database class, which knows specific database implementation.
	/// The Database class will be loaded from a DLL and an object created.
	/// </summary>
	public interface IDb : IDisposable
    {
        string Id { get; set; }
        string DatabaseBrandAndVersion { get; }

        //IDbConnection Connection { get; }

        #region COMMANDS

        IDbCommand CreateQueryCommand(string sql);

		// template has {n} replacements for params; descriptor defines types, directions, sizes e.t.c.
		// for example, template: "select * from my_table where product_id={0}".
		// parameter, passed to the function has the name: "PRODUCT_ID"
		// the {0} sequence will be replaced with :PRODUCT_ID for Oracle and with @PRODUCT_ID for SQL Server
		/*
			<param_descriptors>
				<param_descriptor name=":PROCESS_ID" type="Int32" direction="Input" />
				<param_descriptor name=":DESCRIPTION" type="String" direction="Input" nullable="true" precision="0" scale="0" size="200" source_column=":DESCRIPTION" row_version="Current"/>
			</param_descriptors>
		*/
		IDbCommand CreateQueryCommand(string sqlTemplate, string parameterDescriptorXml, params object [] values);
		IDbCommand CreateQueryCommand(string sqlTemplate, params IDbParameter [] dbParameters);
		IDbCommand CreateQueryCommand(string sqlTemplate, List<IDbParameter> parameters);

		IDbCommand CreateProcedureCommand(string procedureName, string parameterDescriptorXml, params object [] values);
		IDbCommand CreateProcedureCommand(string procedureName, params IDbParameter [] parameters);
        IDbCommand CreateProcedureCommand(string procedureName, List<IDbParameter> parameters);

		void SetCommandParameterValue(IDbCommand command, int parameterIndex, object value);
		void SetCommandParameterValue(IDbCommand command, string parameterName, object value);

		// proc definition sql is a valid SQL create procedure statement
		IProcedureDescriptor ParseProcedureDefinitionSql(string procedureDefinitionSql);
		IDbCommand CreateProcedureCommand(IProcedureDescriptor procedureDescriptor);

        //IDbCommand CreateSelectTopNQueryCommand(string tableName, string fieldList, string where, string endOfQuery, int count);
        //IDbCommand CreateSelectTopNQueryCommand(string selectStatement, int count);
        //IDbCommand CreateSelectTopNQueryCommand(IDbCommand select, int count);

        #endregion // COMMANDS

        #region DATA ADAPTERS

        IDbDataAdapter CreateDataAdapter(string selectStatement);
		IDbDataAdapter CreateDataAdapter(string selectStatement, bool generateAllCommands);
		IDbDataAdapter CreateDataAdapter(IDbCommand selectCommand);
		IDbDataAdapter CreateDataAdapter(IDbCommand selectCommand, bool generateAllCommands);
        void SetDataAdapterUpdateBatchSize(IDbDataAdapter dataAdapter, int batchSize);

        #endregion // DATA ADAPTERS

        #region EXECUTION

        int ExecuteNonQuery(IDbCommand command);
		object ExecuteScalar(IDbCommand command);
		IDataReader ExecuteReader(IDbCommand command);

		DataSet FillDataSet(IDbDataAdapter dataAdapter);
        DataSet FillDataSet(List<IDbDataAdapter> dataAdapters);
		DataSet FillDataSet(IDbDataAdapter dataAdapter, string tableName);
        DataSet FillDataSet(List<IDbDataAdapter> dataAdapters, List<string> tables);

		DataTable FillDataTable(IDbDataAdapter dataAdapter);

		void UpdateDataSet(IDbDataAdapter dataAdapter, DataSet dataSet);
		void UpdateDataSet(IDbDataAdapter dataAdapter, string tableName, DataSet dataSet);
        void UpdateDataSet(List<IDbDataAdapter> dataAdapters, List<string> tables, DataSet dataSet);

		void UpdateDataTable(IDbDataAdapter dataAdapter, DataTable dataTable);
		void UpdateDataRows(IDbDataAdapter dataAdapter, DataRow [] rows);

        #endregion // EXECUTION

        #region DB SPECIFIC

        string ParameterPrefix { get; }
        string ToDbDateTimeString(DateTime dateTime);
        bool IsDbException(Exception exception);

        //Int64 GenerateUniqueSequenceNumber(string sequenceName); // uses database specific implementation to generate a unique sequential number
        //string GetDataTypeName(DbType type);

        #endregion // DB SPECIFIC

        #region DATE TIME

        string CurrentGmtDateTimeFunction { get; } // returns database dependent expression that refers to the current GMT date and time
        string CurrentDateTimeFunction { get; } // returns database dependent expression that refers to the current date and time
		string CurrentDateTimePlusDays(int days); // returns database dependent expression that adds specified number of days to the current date and time
		string CurrentDateTimePlusSeconds(int seconds); // returns database dependent expression that adds specified number of seconds to the current date and time

        DateTime MinDateTime();
        DateTime MaxDateTime();

        #endregion // DATE TIME

        #region TRANSACTIONS

        IDbTransaction Transaction { get; }

		IDbTransaction BeginTransaction();
		void CommitTransaction();
		void RollbackTransaction();

        #endregion // TRANSACTIONS

        #region BULK COPY

        bool CanBulkCopy { get; }

        long BulkCopy(string sDestinationTable, DataTable sourceTable, TimeSpan timeout);
        long BulkCopy(string sDestinationTable, DataTable sourceTable, int batchSize, TimeSpan timeout);
        long BulkCopy(string sDestinationTable, DataRowCollection rows, TimeSpan timeout);
        long BulkCopy(string sDestinationTable, DataRowCollection rows, int batchSize, TimeSpan timeout);
        long BulkCopy(string sDestinationTable, IDataReader reader, TimeSpan timeout);
        long BulkCopy(string sDestinationTable, IDataReader reader, int batchSize, TimeSpan timeout);

        #endregion // BULK COPY

    }



}
